package src;

import src.Base.Symbol2;
import src.Base.SyntaxWord;
import src.Base.WordType;
import src.LLVM.cal.*;
import src.LLVM.control.BrIR;
import src.LLVM.control.CallIR;
import src.LLVM.control.IcmpIR;
import src.LLVM.control.ReturnIR;
import src.LLVM.mem.AllocaIR;
import src.LLVM.mem.LoadIR;
import src.LLVM.mem.StoreIR;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ListIterator;
import java.util.concurrent.ThreadPoolExecutor;

public class LlvmGeneratror {
    int floor = 0;
    SyntaxWord root;
    String tab = "\t";
    static int regId = 1;
    static int blockId = 1;
    HashMap<String, SyntaxWord> global;
    ArrayList<SyntaxWord> stack;
    HashMap<SyntaxWord, Integer> floorMap = new HashMap<>();
    SyntaxWord FatherLAnd = null;
    SyntaxWord FatherLOr = null;
    public LlvmGeneratror(SyntaxWord root){
        File f = new File("llvm_ir.txt");
        if(f.exists()){
            f.delete();
        }
        String init = "declare i32 @getint()\ndeclare void @putint(i32)\ndeclare void @putch(i32)\ndeclare void @putstr(i8*)\n";
        writeRes(init);
        this.root = root;
        stack = new ArrayList<>();
        global = new HashMap<>();
    }
    public void generate(){
        handle(root);
    }
    private void handle(SyntaxWord node){;
        if(node.isEnd()){
            //System.out.println("handle:"+node.getToken().getContent());
            return;
        }
        //System.out.println("handle:<"+node.getType()+">");
        if(node.typeCheck("CompUnit") || node.typeCheck("Decl") ||node.typeCheck("ConstDecl") || node.typeCheck("VarDecl")){
            for (SyntaxWord child:node.getChildren()){
                handle(child);
            }
        }else if (node.typeCheck("ConstDef")){
            ConstDef(node);
        } else if (node.typeCheck("ConstInitVal")) {
            ConstInitVal(node);
        } else if (node.typeCheck("ConstExp")) {
            ConstExp(node);
        } else if (node.typeCheck("VarDef")){
            VarDef(node);
        } else if (node.typeCheck("InitVal")) {
            InitVal(node);
        } else if (node.typeCheck("FuncDef")) {
            FuncDef(node);
        } else if (node.typeCheck("FuncFParams")){
            FuncFParams(node);
        } else if (node.typeCheck("FuncFParam")) {
            FuncFparam(node);
        } else if (node.typeCheck("MainFuncDef")) {
            MainFuncDef(node);
        } else if (node.typeCheck("Block")) {
            Block(node);
        } else if (node.typeCheck("Stmt")) {
            Stmt(node);
        } else if (node.typeCheck("ForStmt")) {
            ForStmt(node);
        } else if (node.typeCheck("Exp")){
            Exp(node);
        } else if (node.typeCheck("Cond")){
            Cond(node);
        } else if (node.typeCheck("LVal")) {
            LVal(node);
        } else if (node.typeCheck("NumBer")) {
            Number(node);
        } else if (node.typeCheck("FuncRParams")){
            FuncRParams(node);
        } else if (node.typeCheck("AddExp")) {
            AddExp(node);
        } else if (node.typeCheck("MulExp")) {
            MulExp(node);
        } else if (node.typeCheck("UnaryExp")){
            UnaryExp(node);
        } else if (node.typeCheck("PrimaryExp")) {
            PrimaryExp(node);
        } else if (node.typeCheck("LOrExp")) {
            FatherLOr = node;
            MyLOrExp(node);
            FatherLOr = null;
        } else if (node.typeCheck("LAndExp")) {
            FatherLAnd = node;
            LAndExp(node);
            FatherLAnd = null;
        } else if (node.typeCheck("EqExp")) {
            EqExp(node);
        } else if (node.typeCheck("RelExp")) {
            RelExp(node);
        }

    }
    private void MyLOrExp(SyntaxWord node){
        ArrayList<SyntaxWord> children = node.getChildren();
        String TOPLORright;
        if(children.size() == 1) {//单推LANd,传值后处理，进LAnd
            SyntaxWord lAndExp = children.get(0);
            lAndExp.setTrueId(node.getTrueId());
            lAndExp.setFalseId(node.getFalseId());
            lAndExp.setStmtId(node.getStmtId());
            handle(lAndExp);
            node.setValue(lAndExp.getValue());
            TOPLORright = lAndExp.getValue();
        }else{// 三节点，递归处理
            // 左杈LOr true 同父级， False开新的给lAnd，
            SyntaxWord lOrExp = children.get(0);
            SyntaxWord lAndExp = children.get(2);
            lOrExp.setTrueId(node.getTrueId());
            lOrExp.setFalseId(blockId++);
            MyLOrExp(lOrExp);
            String resReg = "%x" + regId;
            String left = "0";
            String right = lOrExp.getValue();
            writeRes(new IcmpIR(resReg, left, "ne", right) + "\n");
            String trueBlock = "block" + node.getTrueId();
            String falseBlock = "block" + lOrExp.getFalseId();
            regId++;
            writeRes(new BrIR(resReg, trueBlock, falseBlock) + "\n");
            writeRes("\nblock" + lOrExp.getFalseId()+":\n");
            blockId++;
            lAndExp.setFalseId(node.getFalseId());
            handle(lAndExp);
            node.setValue(lAndExp.getValue());
            TOPLORright = lAndExp.getValue();

        }
        if(node.equals(FatherLOr)){
            String cond = "%x" + regId;
            String trueBlock = "block" + node.getTrueId();
            String falseBlock= "block" + node.getFalseId();
            ++regId;
            writeRes(new IcmpIR(cond, "0", "ne", TOPLORright) + "\n"
                    + new BrIR(cond, trueBlock, falseBlock)  + "\n");
        }
    }



    private void LOrExp(SyntaxWord node) {// Bug
        //LOrExp → LAndExp | LOrExp '||' LAndExp
        // LOR -> LAnd ->  LAndExp '&&' EqExp 特殊
        ArrayList<SyntaxWord> children = node.getChildren();
        if(!children.get(0).isEnd() && children.get(0).typeCheck("LAndExp")){// 单推LAndExp
            //LAndExp
            SyntaxWord lAndExp = children.get(0);
            if(lAndExp.getChildren().size() != 1){
                lAndExp.setStmtId(node.getStmtId());
                lAndExp.setTrueId(node.getTrueId());
                lAndExp.setFalseId(blockId);
                blockId++;
                handle(lAndExp);
                writeRes("\nblock" + lAndExp.getFalseId() + ":\n");
            }else {
                handle(lAndExp);
                String resReg = "%x" + regId;
                String left = "0";
                String right = lAndExp.getChildren().get(0).getValue();
                String trueBlock = "block" + node.getTrueId();
                String falseBlock = "block"  + node.getFalseId();
                writeRes(new IcmpIR(resReg, left, "ne", right) + "\n");
                writeRes(new BrIR(resReg, trueBlock, falseBlock) + "\n");
                ++regId;
            }
        }else{// 左杈LOr， 右杈LAnd
            //LOrExp '||' LAndExp
            SyntaxWord lOrExp = children.get(0);
            if(lOrExp.getChildren().get(0).getChildren().size() == 3){//lOrExp.getChildren().get(0).getChildren().size() == 3
                // LOr 的 0号节点有三个子节点，
                // 首先LOr -> LAnd即LAnd有三个子节点
                // LOr -> LAnd -> LAndExp '&&' EqExp
                lOrExp.setTrueId(node.getTrueId());
                lOrExp.setStmtId(node.getStmtId());
                lOrExp.setFalseId(blockId);
                blockId++;
                handle(lOrExp);
                writeRes("\nblock" + lOrExp.getFalseId() + ":\n");
            }else {
                // LOr -> LAnd
                SyntaxWord lAnd = lOrExp.getChildren().get(0);
                lAnd.setTrueId(node.getTrueId());
                lAnd.setStmtId(node.getStmtId());
                lAnd.setFalseId(blockId);
                blockId++;
                handle(lAnd);
                writeRes(new IcmpIR("%x" + regId, "0", "ne", children.get(0).getChildren().get(0).getChildren().get(0).getValue()) + "\n");
                writeRes(new BrIR("%x" + regId, "block" + node.getTrueId(), "block" + blockId) + "\n");
                writeRes("\nblock" + blockId + ":\n");
                blockId++;
                ++regId;
            }
            SyntaxWord lAndExp = children.get(2);
            if(children.get(2).getChildren().size() == 1){
                handle(lAndExp);
                String resReg = "%x" + regId;
                String left = "0";
                String right = lAndExp.getValue();
                String TrueBlock = "block" + node.getTrueId();
                String FalseBlock = "block" + node.getFalseId();
                writeRes(new IcmpIR(resReg, left, "ne" ,right) + "\n");
                writeRes(new BrIR(resReg, TrueBlock, FalseBlock) + "\n");
                ++regId;
            }else{
                lAndExp.setTrueId(node.getTrueId());
                lAndExp.setStmtId(node.getStmtId());
                lAndExp.setFalseId(node.getFalseId());
                ++regId;
                handle(lAndExp);
            }

        }

    }
    private void LAndExp(SyntaxWord node) {
        // LAndExp → EqExp | LAndExp '&&' EqExp
        ArrayList<SyntaxWord> children = node.getChildren();
        if(children.size() == 1){//单节点无需计算直接向上传值
            SyntaxWord eqExp = children.get(0);
            handle(eqExp);
            node.setValue(eqExp.getValue());
        }else{ // 三节点，递归处理后传值
            SyntaxWord lAndExp = children.get(0);
            lAndExp.setFalseId(node.getFalseId());
            LAndExp(lAndExp);
            String resReg = "%x" + regId;
            String left = "0";
            String right = lAndExp.getValue();
            writeRes(new IcmpIR(resReg, left, "ne", right) + "\n");
            String trueBlock = "block" + blockId;
            String falseBlock = "block" + node.getFalseId();
            regId++;
            writeRes(new BrIR(resReg, trueBlock, falseBlock) + "\n");
            writeRes("\nblock" + blockId+":\n");
            blockId++;
            SyntaxWord eqExp = children.get(2);
            handle(eqExp);
            node.setValue(eqExp.getValue());
            // 当前节点是顶级LAnd节点才需输出如下
            if(node.getTrueId() == 0){
                return;
            }
            if(node.equals(FatherLAnd)){
                String cond = "%x" + regId;
                resReg = cond;
                right = eqExp.getValue();
                trueBlock = "block" + node.getTrueId();
                falseBlock= "block" + node.getFalseId();
                ++regId;
                writeRes(new IcmpIR(cond, left, "ne", right) + "\n"
                        + new BrIR(resReg, trueBlock, falseBlock)  + "\n");
            }
        }
    }

    private void EqExp(SyntaxWord node) {
        RelExp(node);
    }

    private void RelExp(SyntaxWord node) {
        // EqExp → RelExp | EqExp ('==' | '!=') RelExp
        // RelExp → AddExp | RelExp ('<' | '>' | '<=' | '>=') AddExp
        ArrayList<SyntaxWord> children = node.getChildren();
        handle(children.get(0));
        String leftValue = children.get(0).getValue();
        if(children.size() == 1){//单值情况直接向上传值
            node.setValue(leftValue);
        }else{ //计算所有节点值后向上传值
            SyntaxWord right = children.get(2);
            String op = children.get(1).getToken().getContent();
            handle(right);
            String rightValue = right.getValue();
            if(floor == 0){ // 全局声明，纯值无需递归处理
                children.get(2).setValue(calculateNum(leftValue, op, rightValue));
            }else {
                String resReg = "%x" + regId;
                writeRes(new IcmpIR(resReg, leftValue, op, rightValue) + "\n");
                String val = resReg;
                ++regId;
                resReg = "%x" + regId;//TODO
                writeRes(new ZextIR(resReg, val) + "\n");
                children.get(2).setValue(resReg);
                children.get(2).setRegId(resReg);
                ++regId;
            }
            leftValue = children.get(2).getValue();
            node.setValue(leftValue);
        }
    }

    private void AddExp(SyntaxWord node) {
        MulExp(node);
    }

    private void MulExp(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        SyntaxWord left = children.get(0);
        handle(left);
        String leftValue = left.getValue();
        if(children.size() == 1){ // 单表达式不运算
            //直接向上传值
            node.setRegId(left.getRegId());
            node.setValue(leftValue);
            node.setSymbol(left.getSymbol());
        }else{
            //运算  add-> add (+ || -) mul
            // mul (* || /) Unary
            // 运算后向上传值
            String op = children.get(1).getToken().getContent();
            SyntaxWord right = children.get(2);
            handle(right);
            String rightValue = right.getValue();
            boolean isAllNum = true;
            for(SyntaxWord child:children){
                if (!child.isEnd()&&!isNum(child.getValue())){
                    isAllNum = false;
                    break;
                }
            }
            if(isAllNum){
                right.setValue(calculateNum(leftValue, op, rightValue));
            }else {
                writeRes(calIR(leftValue, op, rightValue) + "\n");
                right.setRegId("%x" + regId);
                right.setValue("%x" + regId);
                ++regId;
            }
            node.setSymbol(right.getSymbol());
            node.setValue(right.getValue());
        }
    }

    private String calculateNum(String leftValue, String op, String rightValue) {
        int left = Integer.parseInt(leftValue);
        int right = Integer.parseInt(rightValue);
        String res = "None";
        switch(op){
            case "+"->{res = String.valueOf(left + right);}
            case "-"->{res = String.valueOf(left - right);}
            case "*"->{res = String.valueOf(left * right);}
            case "/"->{res = String.valueOf(left / right);}
            case "%"->{res = String.valueOf(left % right);}
            case "=="->{ res = String.valueOf((left == right) ? 1 : 0);}
            case "!="->{ res = String.valueOf((left != right) ? 1 : 0);}
            case ">"->{ res = String.valueOf((left > right) ? 1 : 0);}
            case ">="->{ res = String.valueOf((left >= right) ? 1 : 0);}
            case "<"->{ res = String.valueOf((left < right) ? 1 : 0);}
            case "<="->{ res = String.valueOf((left <= right) ? 1 : 0);}
        }
        if (res.equals("None")){
            System.out.println("None result error in caculateNum");
            System.exit(-2);
        }
        return res;
    }

    private String calIR(String leftValue, String op, String rightValue) {
        String Ir = "";
        String resAddress = "%x" + regId;
        switch (op){
            case "+"->{
                Ir = new AddIR(resAddress, leftValue, rightValue).toString();
            }
            case "-"->{
                Ir = new SubIR(resAddress, leftValue, rightValue).toString();
            }
            case "*"->{
                Ir = new MultIR(resAddress, leftValue, rightValue).toString();
            }
            case "/"->{
                Ir = new SDivIR(resAddress, leftValue, rightValue).toString();
            }
            case "%"->{
                Ir = new SremIR(resAddress, leftValue, rightValue).toString();
            }
        }
        return Ir;
    }

    private void UnaryExp(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        // UnaryExp → PrimaryExp | Ident '(' [FuncRParams] ')'| UnaryOp UnaryExp
        if(!children.get(0).isEnd() && children.get(0).getType().equals("PrimaryExp")){
            SyntaxWord primaryExp = children.get(0);
            handle(primaryExp);
            node.setValue(primaryExp.getValue());
            node.setRegId(primaryExp.getRegId());
            node.setSymbol(primaryExp.getSymbol());
        }
        else if (!children.get(0).isEnd() && children.get(0).getType().equals("UnaryOp")) {
            String unaryOp = children.get(0).getChild0Content();
            SyntaxWord unaryExp = children.get(1);
            handle(unaryExp);
            switch (unaryOp){
                case"+"->{
                    node.setValue(unaryExp.getValue());
                }
                case "-"->{
                    if(floor == 0){
                        int preValue = Integer.parseInt(unaryExp.getValue());
                        preValue = -preValue;
                        node.setValue(String.valueOf(preValue));
                    }else{
                        String left = "0";
                        String right = unaryExp.getValue();
                        writeRes(calIR(left, "-", right) + "\n");
                        String reg = "%x" + regId;
                        node.setRegId(reg);
                        node.setValue(reg);
                        ++regId;
                    }
                }
                case"!"->{
                    String resReg = "%x" + regId;
                    String left = "0";
                    String right = unaryExp.getValue();
                    writeRes(new IcmpIR(resReg, left, "eq", right) + "\n");
                    String val = resReg;
                    ++regId;
                    resReg = "%x" + regId;
                    writeRes(new ZextIR(resReg, val) + "\n");
                    node.setValue(resReg);
                    node.setRegId(resReg);
                    ++regId;

                }
            }
        }
        else if(children.get(0).isEnd() && children.get(0).getToken().getType().equals(String.valueOf(WordType.IDENFR))){
            //TODO
            SyntaxWord ident = children.get(0);
            String func_name = ident.getToken().getContent();
            SyntaxWord funcSymbol = global.get(func_name);
            String reType = funcSymbol.getReturnType();
            String resReg = "%x" + regId;
            CallIR callIR;
            if(children.size() == 3){
                //Ident() size = 3
                callIR = new CallIR(resReg, reType, func_name);
            }else {
                //Ident ( FuncRParams ) size =4
                SyntaxWord funcRParams = children.get(2);
                handle(funcRParams);
                resReg = "%x" + regId;
                String params = funcRParams.getValue();
                callIR = new CallIR(resReg, reType, func_name, params);
            }
            writeRes(callIR + "\n");
            if(!reType.equals("void")){
                node.setValue(resReg);
                ++regId;
            }
        }
    }

    private void PrimaryExp(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        if(children.get(0).isEnd() && children.get(0).getToken().getType().equals("LPARENT")){
            SyntaxWord exp = children.get(1);
            handle(exp);
            node.setValue(exp.getValue());
        }else if(!children.get(0).isEnd()&&children.get(0).getType().equals("LVal")){
            SyntaxWord lVal = children.get(0);
            LVal(lVal);
            node.setValue(lVal.getValue());
            node.setSymbol(lVal.getSymbol());
            node.setValue(lVal.getValue());
        }else if(!children.get(0).isEnd() && children.get(0).getType().equals("NumBer")){
            SyntaxWord number = children.get(0);
            Number(number);
            node.setSymbol(new Symbol2(0));
            node.setValue(number.getValue());
        }
    }

    private void FuncRParams(SyntaxWord node) {
        // Exp { ',' Exp }
        ArrayList<SyntaxWord> children = node.getChildren();
        ArrayList<String> params = new ArrayList<>();
        children.forEach(child->{
            if(!child.isEnd()){
                Exp(child);
                String value = child.getSymbol().getAddr() + " " + child.getValue();
                params.add(value);
            }
        });
        int expCount = params.size();
        StringBuilder funcRParamsValue = new StringBuilder();
        for(String param:params){
            funcRParamsValue.append(param);
            expCount--;
            if(expCount == 0){
                break;
            }
            funcRParamsValue.append(", ");
        }
        node.setValue(funcRParamsValue.toString());
    }

    private void Number(SyntaxWord node){
        node.setValue(node.getChild0Content());
    }

    private void ForStmt(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        SyntaxWord lval, exp;
        exp = children.get(2);
        lval = children.get(0);
        LVal(lval);
        Exp(exp);
        String option = exp.getValue();
        String address = lval.getRegId();
        writeRes(new StoreIR(option, address) + "\n");
        BrIR brIR = new BrIR();
        brIR.setDest("%block" + node.getStmtId());
        writeRes(brIR + "\n");
    }

    private void Stmt(SyntaxWord node) {
        ArrayList<SyntaxWord> children  = node.getChildren();
        String stmtType = node.getStmtType();
        switch (stmtType){
            case "Assignment"->{
                // LVal = Exp;
                SyntaxWord lval = children.get(0);
                SyntaxWord exp = children.get(2);
                handle(lval);
                String address = lval.getRegId();
                handle(exp);
                String option = exp.getValue();
                writeRes(new StoreIR(option, address) + "\n");
            }
            case "Exp", "Block" ->{
                children.get(0).setContinueId(node.getContinueId());
                children.get(0).setBreakId(node.getBreakId());
                handle(children.get(0));
            }
            case "Return"->{
                if (children.size() == 2){
                    //return;
                    writeRes(new ReturnIR() + "\n");
                }else {
                    //return exp;
                    SyntaxWord exp = children.get(1);
                    handle(exp);

                    ReturnIR returnIR = new ReturnIR(exp.getValue());//Debug 返回变量时Value是否为%x??
                    writeRes(returnIR + "\n");
                }
            }
            case "Input"->{
                //LVal = getint();
                SyntaxWord lval = children.get(0);
                handle(lval);
                String res = "%x" + regId;
                String address =  lval.getRegId();
                writeRes(tab + res + " = call i32 @getint()" + "\n");
                writeRes(new StoreIR(res, address) + "\n");
                ++regId;

            }
            case "Output"->{
                //'printf''('FormatString{','Exp}')'';'
                // 0        1    2
                ArrayList<String> chars = new ArrayList<>();
                String formatString = children.get(2).getToken().getContent();
                ArrayList<String> results = new ArrayList<>();
                for(char s:formatString.toCharArray()){
                    if(s != '"'){
                        chars.add(String.valueOf(s));
                    }
                }
                for(SyntaxWord tmp:children){
                    if (tmp.isEnd()){
                        continue;
                    }
                    if(tmp.typeCheck("Exp")){
                        handle(tmp);
                        results.add(tmp.getValue());
                    }
                }
                int expIndex = 0;
                //Enhence
                /*
                for(int i = 0; i < chars.size(); i++){
                    String nowChar = chars.get(i);
                    if(nowChar.equals("\\")){
                        writeRes(tab +"call void @putch(i32 10)\n");
                    }
                    if(nowChar.equals("%")){
                        String address = results.get(expIndex);
                        ++expIndex;
                        writeRes(tab+"call void @putint(i32 " + address + ")\n");
                        continue;
                    }
                    int ascii = (int)nowChar.toCharArray()[0];
                    writeRes(tab+"call void @putint(i32 " +  ascii + ")\n");
                }
                 */
                for (int i = 0; i < chars.size();++i) {
                    String nowChar = chars.get(i);
                    if (nowChar.equals("\\")) {
                        writeRes(tab + "call void @putch(i32 10)\n");
                        ++i;
                        continue;
                    }
                    if (nowChar.equals("%")) {
                        String address = results.get(expIndex);
                        ++expIndex;
                        writeRes(tab + "call void @putint(i32 " + address + ")\n");
                        ++i;
                        continue;
                    }
                    int ascii = (int) nowChar.toCharArray()[0];
                    writeRes(tab + "call void @putch(i32 " + ascii + ")\n");
                }
            }
            case "If"->{
                //'if' '(' Cond ')' Stmt [ 'else' Stmt ]
                boolean hasElse = false;
                // 0    1    2   3   4       5      6
                writeRes(tab+ "br label %block" + blockId +"\n\n" + "block" + blockId + ":\n");
                int TrueBlock = blockId + 1;
                int FalseBlock  = 0;
                int stmtId;
                SyntaxWord cond = children.get(2);
                SyntaxWord stmt = children.get(4);
                cond.setTrueId(TrueBlock);
                if(children.size() <= 5){
                    cond.setFalseId(blockId + 2);
                    cond.setStmtId(TrueBlock + 1);
                    stmt.setStmtId(TrueBlock + 1);
                    stmt.setBreakId(node.getBreakId());
                    stmt.setContinueId(node.getContinueId());
                    stmtId = blockId + 2;
                    blockId ++;
                    ++blockId;
                    blockId += 1;
                }else{
                    hasElse = true;
                    int sId = blockId + 3;
                    cond.setStmtId(sId);
                    cond.setFalseId(sId  - 1);
                    SyntaxWord stmt2 = children.get(6);
                    stmt2.setStmtId(sId);
                    stmt2.setContinueId(node.getContinueId());
                    stmt2.setBreakId(node.getBreakId());
                    System.out.println("Sid = " + sId);
                    stmt.setStmtId(sId);
                    stmt.setBreakId(node.getBreakId());
                    stmt.setContinueId(stmt2.getContinueId());
                    FalseBlock = blockId+2;
                    stmtId = 1 + 2 + blockId;
                    blockId++;
                    ++blockId;
                    blockId += 2;
                }
                handle(cond);
                writeRes("\n" + "block" + TrueBlock + ":\n");
                handle(stmt);
                if(!hasElse){

                }else{
                    writeRes("\nblock" + FalseBlock + ":\n");
                    handle(children.get(6));
                }
                writeRes("\n");
                writeRes("block");
                writeRes(stmtId + ":\n");
            }
            case "Break"->{
                int bId = node.getBreakId();
                node.setStmtId(bId);
            }
            case "Continue"->{
                int ContinueId = node.getContinueId();
                node.setStmtId(ContinueId);
            }
            case "Loop"->{
                String newBlockDest = "%block" + blockId;;
                BrIR brIR = new BrIR();
                brIR.setDest(newBlockDest);
                writeRes(brIR + "\n\n" + "block" + blockId + ":\n");
                int condBlock = blockId + 1;
                int trueBlock = blockId + 2;
                int falseBlock = blockId + 3;
                int stmtBlock = blockId + 4;
                blockId += 5;
                int[] forElements = node.getForElements();
                boolean hasFor1, hasFor2, hasCond;
                hasFor1 = (forElements[0] == 1);
                hasFor2 = (forElements[2] == 1);
                hasCond = (forElements[1] == 1);
                //  [ForStmt]  [Cond]  [forStmt]  Stmt
                SyntaxWord[] elements = getForElements(forElements, children);
                SyntaxWord f1, f2, cond, stmt;
                f1 = elements[0]; f2 = elements[2]; cond = elements[1];stmt = elements[3];
                if(hasFor1){
                    dealForStmt(f1, condBlock);
                }else {
                    br2Cond(condBlock);
                }
                if(hasCond){
                    dealCond(cond, trueBlock, falseBlock, condBlock);
                } else{
                    br2TrueBlock(trueBlock, condBlock);
                }
                writeRes("\nblock" + trueBlock + ":\n");
                stmt.setBreakId(falseBlock);
                stmt.setContinueId(stmtBlock);
                stmt.setStmtId(stmtBlock);
                handle(stmt);
                writeRes("\nblock" + stmtBlock + ":\n");
                if(hasFor2){
                    dealForStmt(f2, condBlock);
                }else{
                    br2Cond(condBlock);
                }
                writeRes("\nblock" + falseBlock+":\n");
            }
        }
        if(node.getStmtId() == -1){
            return;
        }
        writeRes(tab + "br label %block" + node.getStmtId() + "\n");

    }

    private void dealCond(SyntaxWord cond, int trueBlock, int falseBlock, int condBlock) {
        writeRes("\nblock" + condBlock + ":\n");
        cond.setTrueId(trueBlock);
        cond.setFalseId(falseBlock);
        cond.setStmtId(condBlock);
        handle(cond);
    }

    private void br2TrueBlock(int trueBlock, int condBlock) {
        writeRes("\nblock" + condBlock + ":\n");
        writeRes(new BrIR("%block" + trueBlock, 1) +"\n");
    }

    private void dealForStmt(SyntaxWord forStmt, int CondId){
        forStmt.setStmtId(CondId);
        handle(forStmt);
    }
    private void br2Cond(int condId){
        writeRes(new BrIR("%block"+condId,1)+"\n");
    }
    private SyntaxWord[] getForElements(int[] forElements, ArrayList<SyntaxWord> children) {
        SyntaxWord[] ans = {null, null, null, children.get(children.size() - 1)};
        //'for' '(' [ForStmt] ';' [Cond] ';' [forStmt] ')' Stmt
        int a = forElements[0];
        int b = forElements[1];
        int c = forElements[2];
        if(forExits(a,b,c,0,0,0)){

        }else if(forExits(a,b,c,0,0,1)){
            //'for' '('  ';'  ';' [forStmt] ')'
            ans[2] = children.get(4);
        }else if(forExits(a,b,c,0,1,0)){
            //'for' '('  ';' [Cond] ';'  ')'
            ans[1] = children.get(3);
        }else if(forExits(a,b,c,0,1,1)){
            //'for' '('  ';' [Cond] ';' [forStmt] ')' null, 3,5
            ans[1] = children.get(3);
            ans[2] = children.get(5);
        }else if(forExits(a,b,c,1,0,0)){
            //'for' '(' [ForStmt] ';' [Cond] ';' [forStmt] ')'
            ans[0] = children.get(2);
        }else if(forExits(a,b,c,1,0,1)){
            //'for' '(' [ForStmt] ';'  ';' [forStmt] ')'
            ans[0] = children.get(2);
            ans[2] = children.get(5);
        }else if(forExits(a,b,c,1,1,0)){
            //'for' '(' [ForStmt] ';' [Cond] ';'  ')'
            ans[0] = children.get(2);
            ans[1] = children.get(4);
        }else if(forExits(a,b,c,1,1,1)){
            //'for' '(' [ForStmt] ';' [Cond] ';' [forStmt] ')'
            ans[0] = children.get(2);
            ans[1] =children.get(4);
            ans[2] = children.get(6);
        }
        return ans;
    }
    private boolean forExits(int a,int b,int c,int a_1, int b_1, int c_1){
        return  a == a_1 && b==b_1 && c == c_1;
    }
    private void Block(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        // Block → '{' { BlockItem } '}'
        for (SyntaxWord child:children){
            if(child.isEnd() && child.getToken().getContent().equals("{")){
                floor++;
                if(floor == 1){
                    int i = stack.size()  - 1;
                    while (i >= 0){
                        SyntaxWord tmp = stack.get(i);
                        if(stackFloorCheck(i, 1) && stackRegIdCheck(i, "")){
                            String reg = getReg();
                            String type = stack.get(i).getSymbol().getAddr();
                            writeRes(tab + reg + " = alloca " + type + "\n");
                            tmp.setRegId(reg);
                            writeRes(tab + "store " + type + " " + tmp.getValue() + ", " + type + " * " + reg +"\n");
                            ++regId;
                        }
                        i--;
                    }
                }
            }else if(child.isEnd() && child.getToken().getType().equals("RBRACE")){
                flushNowFloor();
                floor--;
            }else{
                //Decl | stmt;
                if(!child.isEnd()){
                    SyntaxWord blockitem = child.getChildren().get(0);
                    blockitem.setContinueId(node.getContinueId());
                    blockitem.setBreakId(node.getBreakId());
                    handle(blockitem);
                }
            }
        }

    }

    private void flushNowFloor() {
        for(int i = stack.size() - 1; i >= 0;i--){
            if(stackFloorCheck(i, floor)){
                stack.remove(i);
            }
        }
    }

    private void Exp(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        SyntaxWord addExp= children.get(0);
        handle(addExp);
        node.setSymbol(addExp.getSymbol());
        node.setValue(addExp.getValue());
        node.setRegId(addExp.getRegId());
    }

    private void Cond(SyntaxWord node) {
        int trueId, falseId ,stmtId;
        trueId = node.getTrueId();
        falseId = node.getFalseId();
        stmtId = node.getStmtId();
        SyntaxWord lorExp = node.getChildren().get(0);
        lorExp.setTrueId(trueId);
        lorExp.setFalseId(falseId);
        lorExp.setStmtId(stmtId);
        handle(lorExp);
        node.setValue("%x" + regId);
        ++regId;
    }

    private void LVal(SyntaxWord node) {
        //Ident size = 1
        //Ident [Exp] size =  4
        //Ident [Exp][Exp] size = 7
        ArrayList<SyntaxWord> children = node.getChildren();
        int LValType =children.size();
        SyntaxWord ident = children.get(0);
        String ident_name = ident.getToken().getContent();
        SyntaxWord identSymbol = querySymbolOnStack(ident_name);
        Symbol2 k = null;
        if (identSymbol == null){//全局变量
            k = global.get(ident_name).getSymbol();
            identSymbol = global.get(ident_name);
            if(identSymbol == null){
                //e
                System.out.println("no Define");
            }
            if(floor == 0){// 全局变量赋值;
                assert identSymbol != null;
                switch (LValType){
                    case 1->{
                        node.setValue(identSymbol.getSymbol().getIntVal());
                    }
                    case 4->{
                        SyntaxWord exp = children.get(2);
                        Exp(exp);
                        int i = Integer.parseInt(exp.getValue());
                        node.setValue(identSymbol.getSymbol().getDim1().get(i));
                    }
                    case 7->{
                        SyntaxWord exp1,exp2;
                        exp1 = children.get(2);
                        exp2 = children.get(5);
                        Exp(exp1);
                        handle(exp2);
                        int x,y;
                        x = Integer.parseInt(exp1.getValue());
                        y = Integer.parseInt(exp2.getValue());
                        node.setValue(identSymbol.getSymbol().getDim2()[x][y]);
                    }
                }
            }else {
                //块内使用全局变量
                switch (LValType){
                    //二维数组元素使用
                    case 7->{
                        SyntaxWord exp1,exp2;
                        exp1 = children.get(2);
                        exp2 = children.get(5);
                        Exp(exp1);
                        handle(exp2);
                        int x,y;
                        x = k.getX();
                        y = k.getY();
                        String srcReg = "%x" + (regId + 1);
                        String address = "%x" + regId;
                        regId += 2;
                        String geteIR = tab + address + " = getelementptr [" + x + " x [" + y + " x i32]], ["
                                + x + " x [" + y + " x i32]]" + "* @" + ident_name + ", i32 0, i32 " + exp1.getValue()+
                                ", i32 " + exp2.getValue() + "\n";
                        writeRes(geteIR);
                        writeRes(new LoadIR(srcReg, address) + "\n");
                        node.setValue(srcReg);
                        node.setRegId(address);
                    }
                    //一维数组元素使用 或 二维数组部分使用
                    case 4->{
                        SyntaxWord exp = children.get(2);
                        Exp(exp);
                        if(k.getDim() == 1){
                            String res = "%x"+regId;
                            String base = "@" + ident_name;
                            int len = k.getX();
                            String tmp ="\t" + res + " = getelementptr [" + len + " x i32]," +
                                    " [" + len + " x i32]* " + base + ", i32 0, i32 " + exp.getValue()+ "\n";
                            writeRes(tmp);
                            writeRes(new LoadIR("%x"+(regId+1), res)+"\n");
                            k.setAddr("i32");
                            regId++;
                            node.setValue("%x"+regId);
                            node.setRegId(res);
                            regId++;
                        }else if(k.getDim() == 2){
                            String res = "%x" + regId;
                            String op1, op2;
                            op1 = exp.getValue();
                            op2 = String.valueOf(k.getY());
                            ++regId;
                            writeRes(new MultIR(res, op1, op2) + "\n");
                            int m, n;
                            m = k.getX();
                            n = k.getY();
                            writeRes(tab+"%x"+regId+" = getelementptr ["+m+" x ["+n+" x i32]], ["+m+" x ["+n+" x i32]]* @"+ident_name+", i32 0, i32 0\n");
                            ++regId;
                            writeRes(GepIrDim2("%x" + regId, String.valueOf(n), "%x" + (regId - 1), "%x" + (regId - 2) + "\n"));
                            k.setAddr("i32*");
                            node.setValue("%x" + regId);
                            node.setRegId("%x" + regId);
                            ++regId;
                        }
                    }
                    //普通变量使用 或 传参一维数组首地址， 或传参二维数组首地址
                    case 1->{
                        int dim = k.getDim();
                        switch (dim){
                            case 0->{
                                String address = "@" + ident_name;
                                String res = "%x" + regId;
                                ++regId;
                                writeRes(new LoadIR(res, address) + "\n");
                                node.setValue(res);
                                node.setRegId(address);
                            }
                            case 1->{
                                String res = "%x" + regId;
                                String address = "@" + ident_name;
                                int len = k.getX();
                                k.setAddr("i32*");
                                writeRes(new GepIR(res, len, address) + "\n");
                                node.setValue(res);
                                node.setRegId(res);
                                regId++;
                            }
                            case 2->{
                                String reg = "%x" + regId;
                                int m,n;
                                m = k.getX();
                                n = k.getY();
                                k.setAddr("[" + n + " x i32]*");
                                String s = tab + reg +" = getelementptr ["+ m +" x ["+ n +" x i32]], ["+ m +" x ["+ n +" x i32]]* "+("@" + ident_name)+", i32 0, i32 0\n";
                                writeRes(s);
                                node.setRegId(reg);
                                node.setValue(reg);
                                ++regId;
                            }
                        }
                    }
                }

            }
        }else {// 在栈上
            k = identSymbol.getSymbol();
            switch (LValType){
                case 1->{
                    //使用站上普通变量
                    int dim = k.getDim();
                    if(dim == 0){
                        //Ident   普通变量 = 普通变量
                        k.setAddr("i32");
                        String resReg = "%x" + regId;
                        String address = identSymbol.getRegId();
                        PropagationLVal(node, resReg, address);//RegId ++ DIF: RegId += 2;
                    }
                    else if(dim == 1){
                        //使用栈上一维数组首地址
                        k.setAddr("i32*");
                        /*
                        int func(int arr[]){
                            int brr[2] = {1,2};
                            printf("%d, arr[1]); //k.getX() == 0
                            printf("%d, brr[1]); //k.getX() != 0
                        }
                         */
                        if(k.getX() == 0){
                            //使用定义函数参数中一维数组首地址(传入的一维数组的首地址)
                            String reg1  = "%x" + regId;
                            String address = identSymbol.getRegId();
                            //%x341 = load i32, i32* %x302
                            //%v397 = load i32*, i32* * %v352
                            writeRes(tab+ reg1 + " = load i32*, i32* * "+address + "\n");
                            node.setValue(reg1);
                            node.setRegId(reg1);
                            ++regId;
                        }else{
                            //使用块(父级块)内定义的一维数组的首地址
                            String res = "%x" + regId;
                            int len = k.getX();
                            String base = identSymbol.getRegId();
                            writeRes(new GepIR(res, len, base) + "\n");
                            //k.setAddr("i32*");//DIFF 在ConstDef | VarDef中给数组定义的AddrType已设置为i32* if error delete
                            node.setValue(res);
                            node.setRegId(res);
                            ++regId;// DIF: regId += 2;
                        }
                    }
                    else if(dim == 2){
                        //使用栈上二维数组的首地址
                         /*
                        int func(int arr[]3){
                            int brr[2][2] = {{1,2},{1,2}};
                            printf("%d, arr[1][0]); //k.getX() == 0
                            printf("%d, brr[1][0]); //k.getX() != 0
                        }
                         */
                        if (k.getX() == 0){
                            String reg = "%x" + regId;
                            String address = identSymbol.getRegId();
                            int y = k.getY();
                            k.setAddr("["+y+" x i32]*");
                            String s = tab+reg+" = load ["+ y +" x i32] *, [" + y + " x i32]* * "+address+"\n";
                            writeRes(s);
                            node.setValue(reg);
                            node.setRegId(address);
                            ++regId;
                        }else {
                            String nowReg = "%x" + regId;
                            int m, n;
                            m = k.getX();
                            n = k.getY();
                            String address = identSymbol.getRegId();
                            k.setAddr("["+ n +" x i32]*");
                            String output = tab + nowReg + " = getelementptr [" + m + " x ["
                                    + n +" x i32]], ["
                                    + m +" x ["
                                    + n +" x i32]]*"
                                    + address
                                    +", i32 0, i32 0";
                            writeRes(output + "\n");
                            node.setValue(nowReg);
                            node.setRegId(nowReg);
                            ++regId;
                        }
                    }
                }
                case 4->{ //Ident[Exp]
                    //一维数组元素使用
                    int symbolDim = identSymbol.getSymbol().getDim();
                    int x = k.getX();
                    SyntaxWord exp = children.get(2);
                    Exp(exp);
                    switch (symbolDim){
                        //使用栈上一维数组的元素
                        case  1-> {
                            /*
                            void func(int arr[]){
                                int brr[2] = {1,2};
                                int if_true = arr[0]; // x == 0;
                                int if_false = brr[0]; // x!= 0;
                            }
                             */
                            k.setAddr("i32");
                            if(x == 0){
                                String reg = "%x" + regId;
                                writeRes(tab + reg + " = load i32*, i32* * " + identSymbol.getRegId() + "\n");
                                writeRes(tab + "%x" + (regId+1) + " = getelementptr i32, i32* %x"+ regId +", i32 " + exp.getValue() + "\n");
                                ++regId;
                                node.setRegId("%x" + regId);
                                writeRes(tab + "%x" + (1 + regId) + " = load i32, i32* %x" + regId + "\n");
                                regId++;
                                node.setValue("%x" +  regId);
                                regId++;
                            } else {
                                int m = k.getX();
                                writeRes(tab + "%x" + regId + " = getelementptr [" + m + " x i32], [" + m + " x i32]*" + identSymbol.getRegId() + ", i32 0, i32 " + exp.getValue() + "\n");
                                writeRes(tab + "%x"+(regId+1) + " = load i32, i32* %x" + regId+"\n");
                                node.setRegId("%x"+regId);
                                regId++;
                                node.setValue("%x"+regId);
                                ++regId;
                            }
                        }
                        //使用栈上二维数组的某一行首地址
                              /*
                            void func(int arr[][5]){
                                int brr[2][2] = {{1112,2222},{1111,2222}};
                                int if_true = arr[0][3]; // x == 0;
                                int if_false = brr[0][0]; // x!= 0;
                            }
                             */
                        case 2-> {
                            k.setAddr("i32*");
                            if(x == 0){
                                int len = k.getY();
                                String s = tab + "%x" + regId + " = load [" + len + " x i32] *, [" + len + " x i32]* * "  + identSymbol.getRegId();
                                writeRes(s + "\n");
                                ++regId;
                                s = tab + "%x" + regId + " = getelementptr [" + len+" x i32], [" + len + " x i32]* %x" + (regId - 1) + ", i32 " + exp.getValue();
                                writeRes(s + "\n");
                                regId++;
                                String reg = "%x" + regId;
                                String base = "%x" + (regId - 1);
                                writeRes(new GepIR(reg, len, base) + "\n");
                                node.setValue(reg);
                                node.setRegId(reg);
                            }else {
                                int m, n;
                                String output;
                                m = k.getX();
                                n = k.getY();
                                String res = "%x" + regId;
                                String op1 = exp.getValue();
                                String op2 = String.valueOf(k.getY());
                                writeRes(new MultIR(res, op1, op2) + "\n");
                                regId++;
                                output = tab + "%x" + regId + " = getelementptr [" + m + " x [" + n + " x i32]], [" + m + " x [" + n + " x i32]]*" + identSymbol.getRegId() + ", i32 0, i32 0";
                                writeRes(output + "\n");
                                ++regId;
                                output = tab + "%x" + regId + " = getelementptr [" + n + " x i32], [" + n + " x i32]* %x" + (regId - 1) + ", i32 0, i32 %x" + (regId - 2) ;
                                writeRes(output + "\n");
                                node.setValue("%x" + (regId));
                                node.setRegId("%x" + (regId));
                            }
                            ++regId;
                        }
                    }

                }
                case 7->{
                    //二维数组元素使用
                    SyntaxWord exp1,exp2;
                    exp1 = children.get(2);
                    exp2 = children.get(5);
                    Exp(exp1);
                    Exp(exp2);
                    int m = k.getX();
                    int n = k.getY();
                    // 使用参数中定义的二维数组元素，定义时不规定二维数组行数
                    if(k.getX() == 0){
                        k.setAddr("i32");
                        String s = tab + "%x" + regId + " = load ["+ n +" x i32] *, [" + n + " x i32]* * " + identSymbol.getRegId();
                        writeRes(s + "\n");
                        regId++;
                        s = tab + "%x"+ regId + " = getelementptr [" + n + " x i32], [" + n + " x i32]* " + "%x" + (regId - 1) + ", i32 " + exp1.getValue();
                        writeRes(s + "\n");
                        ++regId;
                        s = tab + "%x" + regId + " = getelementptr [" + n + " x i32], [" + n +" x i32]* %x" + (regId - 1) + ", i32 0, i32 " + exp2.getValue();
                        writeRes(s + "\n");
                        writeRes(new LoadIR("%x" + (1 + regId), "%x" + regId) + "\n");
                        node.setRegId("%x"+ regId);
                        ++regId;
                        node.setValue("%x"+ regId);
                        regId += 1;
                    }
                    // 使用(父)块内定义的二维数组元素
                    else {
                        String loadReg = "%x" + (1 + regId);
                        String loadAddress = "%x"  + regId;
                        writeRes(tab+loadAddress
                                + " = getelementptr ["
                                + m +" x ["
                                + n +" x i32]], ["
                                + m +" x ["
                                + n +" x i32]]*"//TODO BUG
                                + identSymbol.getRegId()
                                + ", i32 0, i32 "
                                + exp1.getValue()
                                + ", i32 "
                                + exp2.getValue()
                                + "\n"
                        );
                        writeRes(new LoadIR(loadReg, loadAddress) + "\n");
                        node.setValue(loadReg);
                        node.setRegId(loadAddress);
                        k.setAddr("i32");
                        regId += 2;
                    }
                }
            }
        }
        node.setSymbol(k);
    }


    private void MainFuncDef(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        writeRes("\n");
        writeRes("define dso_local i32 @main() { \n");
        SyntaxWord block = children.get(4);
        Block(block);
        writeRes("}\n");
    }

    private void FuncFparam(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        SyntaxWord ident = children.get(1);
        floorMap.put(ident, 1);
        int dim = calDim(children);
        String reg = "%x" + regId;
        if(dim == 0){
            writeRes("i32 " + reg);
            ident.setValue(reg);
            ++regId;
            ident.setSymbol(new Symbol2(0));
            stack.add(ident);
        }else if (dim == 1){
            writeRes("i32*" + reg);
            ident.setValue(reg);
            Symbol2 k = new Symbol2(1, 0);
            regId++;
            k.setAddr("i32*");
            ident.setSymbol(k);
            stack.add(ident);
        }else {
            SyntaxWord constExp = children.get(5);
            handle(constExp);
            writeRes("[" + constExp.getValue() + " x i32] *%x" + regId);
            ident.setValue("%x" + regId);
            int y = Integer.parseInt(constExp.getValue());
            Symbol2 k = new Symbol2(2, 0, y);
            k.setAddr("[" + constExp.getValue() + " x i32]*");
            ident.setSymbol(k);
            ++regId;
            stack.add(ident);
        }
    }

    private void FuncFParams(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        if(children.size() == 1){
            FuncFparam(children.get(0));
        }else {
            for(SyntaxWord child:children){
                if(child.isEnd()){
                    writeRes(", ");
                    continue;
                }
                FuncFparam(child);
            }
        }
    }

    private void FuncDef(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        SyntaxWord ident = children.get(1);
        String identContent = ident.getToken().getContent();
        boolean isVoid = children.get(0).getChildren().get(0).getToken().getContent().equals("void");
        String funcType = isVoid ? "void" : "i32";
        if(isVoid){
            ident.setVoid();
        }else {
            ident.setInt();
        }
        String def = "define dso_local " + funcType + " @" + identContent;
        writeRes(def);
        global.put(identContent, ident);
        //if(children.get(2).isEnd() && children.get(2).getToken().getContent().equals("("))
        writeRes("(");
        if(children.size() == 6){
            SyntaxWord funcFParamsNode = children.get(3);
            FuncFParams(funcFParamsNode);
        }
        SyntaxWord blockNode = children.get(children.size() - 1);
        writeRes(") {\n");
        Block(blockNode);
        if (isVoid){
            writeRes(tab + "ret void\n");
        }
        writeRes("}\n\n");
    }

    private void InitVal(SyntaxWord node) {
        ConstInitVal(node);
    }

    private void VarDef(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        SyntaxWord ident = children.get(0);
        // VarDef → Ident { '[' ConstExp ']' } | Ident { '[' ConstExp ']' } '=' InitVal
        int dim = calDim(children);
        if(dim == 0){//普通变量
            if(floor != 0){
                String reg = "%x" + regId;
                writeRes(new AllocaIR(reg)+"\n");
                ident.setValue(reg);
                ident.setRegId(reg);
                regId++;
            }
            Symbol2 tmp = new Symbol2(0);
            ident.setSymbol(tmp);
            if(children.size() == 3){
                SyntaxWord InitVal = children.get(2);
                InitVal.setSymbol(new Symbol2(0));
                handle(InitVal);
                ident.getSymbol().setIntVal(InitVal.getSymbol().getIntVal());
                if(floor != 0){
                    String address = ident.getRegId();
                    writeRes(new StoreIR(InitVal.getValue(), address) + "\n");
                }
            }else{
                ident.getSymbol().setIntVal("0");
            }
            if(floor == 0){
                String res ="@"+ ident.getToken().getContent() + " = dso_local global i32 "+ident.getSymbol().getIntVal() + "\n" ;
                writeRes(res);
            }
        }
        else if(dim == 1){
            //ident [ ConstExp ]
            int preFloor = floor;
            floor = 0;
            SyntaxWord constExp = children.get(2);
            handle(constExp);
            floor = preFloor;
            if(floor != 0){
                String reg = "%x" + regId;
                String address = constExp.getValue();
                writeRes(new AllocaIR(reg, address) + "\n");
                ident.setValue(reg);
                ident.setRegId(reg);
                ++regId;
            }
            Symbol2 tmp = new Symbol2(1, Integer.parseInt(constExp.getValue()));
            tmp.setAddr("i32*");//DIFF if error delete
            ArrayList<String> dim1_value = tmp.getDim1();
            if(children.size() == 4) {
                int x = tmp.getX();
                int i = 0;
                while (i < x){
                    if(floor!=0){
                        dim1_value.add("null");
                    }else {
                        dim1_value.add("0");
                    }
                    i++;
                }
                tmp.setDim1(dim1_value);
            }else{
                SyntaxWord initVal = children.get(5);
                initVal.setSymbol(tmp);
                handle(initVal);
            }
            if(floor != 0){
                dim1_value = tmp.getDim1();
                int i = 0;
                for(String s :dim1_value){
                    if(s.equals("null")){
                        continue;
                    }
                    String reg = "%x" + regId;
                    writeRes(tab + reg + " = getelementptr [" + tmp.getX() + " x i32], [" + tmp.getX() + " x i32]* " + ident.getRegId() + ", i32 0, i32 " + i + "\n");
                    writeRes(new StoreIR(s, reg)+"\n");
                    regId++;
                    ++i;
                }
            }else {
                int x = tmp.getX();
                if(children.size()  == 4){
                    String outPut = "@";
                    outPut = outPut + ident.getToken().getContent() + " = dso_local global [" + tmp.getX() + " x i32] zeroinitializer\n";
                    writeRes(outPut);
                }else {
                    String content = ident.getToken().getContent();
                    writeRes("@" + content + " = dso_local global [" + x + " x i32] [");
                    dim1_value = tmp.getDim1();
                    defArray(dim1_value);
                }
            }
            ident.setSymbol(tmp);// DeBug add
        }
        else if(dim == 2){
            //ident[ConstExp][ConstExp]
            int preFloor = floor;
            floor = 0;
            SyntaxWord constExp1,constExp2;
            constExp1 = children.get(2);
            constExp2 = children.get(5);
            handle(constExp1);
            handle(constExp2);
            floor = preFloor;
            if(floor != 0){
                String reg = "%x" + regId;
                String dim1 = constExp1.getValue();
                String dim2 = constExp2.getValue();
                writeRes(new AllocaIR(reg, dim1, dim2)+"\n");
                ident.setValue(reg);
                ident.setRegId(reg);
                ++regId;
            }
            int x, y;
            x = Integer.parseInt(constExp1.getValue());
            y = Integer.parseInt(constExp2.getValue());
            Symbol2 k = new Symbol2(2,x ,y);
            if(!children.get(children.size() - 1).isEnd() && children.get(children.size() - 1).getType().equals("InitVal")){
                SyntaxWord initVal = children.get(8);
                initVal.setSymbol(k);
                handle(initVal);
            }else{
                String[][] dim2_value = k.getDim2();
                for(int i = 0; i < x;++i){
                    for(int j = 0; j < y;++j){
                        dim2_value[i][j] = floor == 0 ? "0" : "null";
                    }
                }
                k.setDim2(dim2_value);
            }
            ident.setSymbol(k);
            if(floor != 0){
                printDim2Array(ident);
            }else{
                if(children.size() == 7){
                    String cnm = "@" + ident.getToken().getContent() + " = dso_local global [";
                    writeRes(cnm + x + " x ["+ y + " x i32]]" + " zeroinitializer\n");
                }else{
                    writeRes("@" + ident.getToken().getContent() + " = dso_local global [" + x + " x [" + y + " x i32]] [[");
                    String [][] dim2_value = k.getDim2();
                    //printGlobalDim2Array(dim2_value, x, y);
                    writeArray(dim2_value, x, y);
                }
            }
            ident.setSymbol(k);

        }
        if(floor != 0){
            floorMap.put(ident, floor);
            stack.add(ident);
        }else {
            global.put(ident.getToken().getContent(), ident);
        }
    }
    /*
        private void printGlobalDim2Array(String[][] dim2_value, int m, int n) {
            int i ,j;
            String end = dim2_value[m - 1][n - 1];
            for(i = 0; i < m ; ++i){
                writeRes(n + " x i32] [");
                for(j = 0; j < n - 1; ++j){
                    writeRes("i32 " + dim2_value[i][j]);
                    writeRes("], [");
                }
                writeRes("i32 " + dim2_value[i][n - 1] + "], [");
            }
            for(i = 0; i < n - 1; ++i){
                writeRes("i32 " + dim2_value[m - 1][i] + ", ");
            }
            writeRes("i32 " + end + "]]\n");
        }
    */
    private void printDim2Array(SyntaxWord ident) {
        Symbol2 keyValue = ident.getSymbol();
        String[][] dim2_value  = keyValue.getDim2();
        int m = keyValue.getX(), n = keyValue.getY();
        for(int i = 0;i < m;++i){
            for(int j = 0;j < n; ++j){
                if(dim2_value[i][j].equals("null")){
                    continue;
                }
                String address = "%x" + regId;
                writeRes(tab+"%x" + regId+" = getelementptr ["+ m +" x ["+ n +" x i32]], ["+ m +" x ["+ n +" x i32]]* "+ident.getRegId()+", i32 0, i32 "+i+", i32 "+j+"\n");
                writeRes(new StoreIR(dim2_value[i][j], address) + "\n");
                ++regId;
            }
        }
    }

    private void defArray(ArrayList<String> dim1_value) {
        int i = 0;
        int size = dim1_value.size();
        for(String s:dim1_value){
            writeRes("i32 "+s+", ");
            i++;
            if(i == size - 1){
                break;
            }
        }
        writeRes("i32 " + dim1_value.get(size - 1)+"]"+"\n");
    }

    private int calDim(ArrayList<SyntaxWord> children) {
        int dim = 0;
        for(SyntaxWord child:children){
            if (child.isEnd() && child.getToken().getContent().equals("[")){
                dim++;
            }
        }
        return dim;
    }
    private boolean stackFloorCheck(int index, int f){
        SyntaxWord tmp = stack.get(index);
        if(floorMap.containsKey(tmp)){
            int floor = floorMap.get(tmp);
            return floor == f;
        }
        return  false;
    }
    private boolean stackRegIdCheck(int index, String reg){
        SyntaxWord tmp = stack.get(index);
        return tmp.getRegId().equals(reg);
    }
    private void ConstExp(SyntaxWord node) {
        ArrayList<SyntaxWord> children = node.getChildren();
        if(children.size() == 1){
            SyntaxWord AddExp = children.get(0);
            handle(AddExp);
            node.setValue(AddExp.getValue());
        }
    }

    private void ConstInitVal(SyntaxWord node) {
        //ConstInitVal → ConstExp | '{' [ ConstInitVal { ',' ConstInitVal } ] '}'
        ArrayList<SyntaxWord> children = node.getChildren();
        Symbol2 k = node.getSymbol();
        int dim = k.getDim();
        switch (dim) {
            case 0 -> {
                SyntaxWord ConstExp = children.get(0);
                handle(ConstExp);
                k.setIntVal(ConstExp.getValue());
                node.setValue(ConstExp.getValue());
                System.out.println("dim = 0 set " + ConstExp.getValue());
            }
            case 1 -> {
                //{ConstExp,ConstExp,ConstExp···}
                int len = k.getX();
                ArrayList<String> dim1_value = k.getDim1();
                for (SyntaxWord temp : children) {
                    if (temp.isEnd()) {
                        continue;
                    }
                    Symbol2 constExpSymbol = new Symbol2(0);
                    temp.setSymbol(constExpSymbol);
                    handle(temp);
                    dim1_value.add(temp.getValue());
                }
                if (dim1_value.size() < len) {
                    int i = dim1_value.size() - 1;
                    for (; i < len; i++) {
                        if (floor == 0) {
                            dim1_value.add("null");
                        } else {
                            dim1_value.add("0");
                        }
                    }
                }
            }
            case 2 -> {
                //{ConstInitVal, ConstInitVal}
                // ↓
                //{{ConstExp, ConstExp...},{}}
                int len_x, len_y;
                len_x = k.getX();
                len_y = k.getY();
                int m = 0;
                String[][] dim2_value = new String[len_x][len_y];
                for (SyntaxWord temp : children) {
                    if (temp.isEnd()) {
                        continue;
                    }
                    Symbol2 dimension2ConstExpSymbol = new Symbol2(1);
                    dimension2ConstExpSymbol.setX(len_y);
                    temp.setSymbol(dimension2ConstExpSymbol);
                    handle(temp);//处理其中ConstInitVal
                    ArrayList<String> ConstInitValDim1 = temp.getSymbol().getDim1();
                    int i = 0;
                    for (String s : ConstInitValDim1) {
                        dim2_value[m][i] = s;
                        ++i;
                    }
                    ++m;
                }
                if (m < len_x) {
                    for (int i = m; i < len_x; i++) {
                        for (int j = 0; j < len_y; j++) {
                            dim2_value[i][j] = floor == 0 ? "0" : "null";
                        }
                    }
                }
                k.setDim2(dim2_value);
            }
        }
        System.out.println("InitVal:" + node.getValue());
    }

    private void ConstDef(SyntaxWord node) {
        //Ident { '[' ConstExp ']' } '=' ConstInitVal
        ArrayList<SyntaxWord> children = node.getChildren();
        SyntaxWord ident = children.get(0);
        int size  = children.size();
        Symbol2 tmp;
        if(size == 3){
            //普通变量定义
            // Ident  =  ConstInitVal
            if(floor != 0){
                String  s = "%x" + regId;
                ident.setValue(s);
                ident.setRegId(s);
                s = tab + "%x" + regId + " = alloca i32\n";
                writeRes(s);
                ++regId;
            }
            tmp = new Symbol2(0);
            SyntaxWord constInitVal = children.get(2);
            constInitVal.setSymbol(tmp);
            handle(constInitVal);
            tmp.setIntVal(constInitVal.getSymbol().getIntVal());
            ident.setSymbol(tmp);
            String output = "";
            if(floor == 0){
                output += "@" + ident.getToken().getContent() + " = dso_local global i32" + " " + tmp.getIntVal();
            }else {
                output += tab + "store i32 " + constInitVal.getValue() + ", i32* " + ident.getRegId();
            }
            writeRes(output + "\n");
        }
        else if (size == 6) {
            //一维数组定义
            int preFloor = floor;
            floor = 0;
            handle(children.get(2));
            floor = preFloor;
            if(floor != 0){
                writeRes(tab + "%x" + regId + " = alloca [" + children.get(2).getValue() + " x i32]\n");
                ident.setValue("%x" + regId);
                ident.setRegId("%x" + regId);
                // ++regId;
            }
            SyntaxWord ConstInitVal = children.get(5);
            tmp = new Symbol2(1);
            tmp.setAddr("i32*");//DIFF I think def yiWEIcan Set AddrType if error DELETE
            ident.setSymbol(tmp);
            DefArrayDim1(node, ident);
            ConstInitVal.setSymbol(ident.getSymbol());
            handle(ConstInitVal);
            if(floor != 0){
                ArrayList<String> dim1_value = ident.getSymbol().getDim1();
                int i = 0;
                for(String s:dim1_value){
                    if(s.equals("null")){
                        continue;
                    }
                    String address = "%x" + regId;
                    int len = ident.getSymbol().getX();
                    writeRes(tab+"%x"+ regId+" = getelementptr ["+ len +" x i32], ["+ len +" x i32]*"+ident.getRegId()+", i32 0, i32 "+i+"\n");
                    writeRes(new StoreIR(s, address) +"\n");
                    ++regId;
                    ++i;
                }
            }else{
                String res = "@" + ident.getToken().getContent() + " = dso_local constant [" + ident.getSymbol().getX() + " x i32] [";
                writeRes(res);
                ArrayList<String> list = ident.getSymbol().getDim1();
                int len = ident.getSymbol().getX();
                for(int i = 0; i < len ;i++) {
                    String value = list.get(i);
                    if (i == len - 1) {
                        writeRes("i32 " + value + "]\n");
                        break;
                    }
                    if (value.equals("null")) {
                        continue;
                    }
                    writeRes("i32 " + value + ", ");
                }
            }
        }
        else if (size == 9) {
            // <ident>[2][2] = <ConstInitVal>
            int preFloor = floor;
            floor = 0;
            SyntaxWord constExp1 = children.get(2), constExp2 = children.get(5);
            SyntaxWord constInitVal = children.get(8);
            handle(constExp1);
            handle(constExp2);
            floor = preFloor;
            if(floor != 0){
                String reg = "%x"+regId;
                writeRes(new AllocaIR(reg, constExp1.getValue(), constExp2.getValue()) + "\n");
                ident.setRegId("%x"+regId);
                ident.setValue("%x"+regId);
                ++regId;
            }
            int x = Integer.parseInt(constExp1.getValue());
            int y = Integer.parseInt(constExp2.getValue());
            tmp = new Symbol2(2,x,y);
            ident.setSymbol(tmp);
            constInitVal.setSymbol(tmp);
            handle(constInitVal);
            String [][] dim2_value = constInitVal.getSymbol().getDim2();
            if(floor != 0){
                for(int i  = 0; i < x;++i){
                    for(int j = 0; j < y ;++j){
                        if(dim2_value[i][j].equals("null")){
                            continue;
                        }
                        String geteIR = createGeteIR(ident.getRegId(), x, y ,i ,j);
                        writeRes(geteIR);
                        String address = "%x"+regId;
                        writeRes(new StoreIR(dim2_value[i][j], address)+"\n");
                        ++regId;
                    }
                }
            }else{
                String outPut = "@";
                outPut += ident.getToken().getContent();
                outPut += " = dso_local constant [";
                outPut = outPut + x + " x [" + y + " x i32]] [[";
                writeRes(outPut);
                writeArray(dim2_value, x, y);
            }
        }
        if(floor != 0){
            floorMap.put(ident, floor);
            stack.add(ident);
        }else{
            global.put(ident.getToken().getContent(), ident);
        }
    }

    private void writeRes(String s){
        Writer.instance.write("llvm_ir.txt", s);
    }

    private void DefArrayDim1(SyntaxWord node, SyntaxWord idnet){
        ArrayList<SyntaxWord> children = node.getChildren();
        Symbol2 k = idnet.getSymbol();
        int preFloor = floor;
        floor = 0;
        handle(children.get(2));
        floor = preFloor;
        if(floor != 0){
            idnet.setValue("%x" + regId);
            idnet.setRegId("%x" + regId);
            ++regId;
        }
        k.setDim(1);
        int len = Integer.parseInt(children.get(2).getValue());
        k.setX(len);
    }

    private void writeArray(String[][] array, int m, int n){
        int i = 0;
        while(i < m - 1){
            writeRes(n + " x i32] [");
            for (int j = 0; j < n - 1;j++){
                writeRes("i32 " + array[i][j] + ", ");
            }
            writeRes("i32 " + array[i][n - 1] + "], [");
            ++i;
        }
        writeRes(n + " x i32] [");
        int j = 0;
        while(j < n - 1){
            writeRes("i32 " + array[m - 1][j]+", ");
            ++j;
        }
        writeRes("i32 " + array[m - 1][n - 1] + "]]\n");
    }

    private String createGeteIR(String identReg, int x, int y ,int i ,int j){
        return tab + "%x" + regId + " = getelementptr [" + x + " x [" + y + " x i32]], [" + x + " x [" + y + " x i32]]* " + identReg + ", i32 0, i32 " + i + ", i32 " + j + "\n";
    }
    private String getReg(){
        return "%x" + regId;
    }


    private SyntaxWord querySymbolOnStack(String ident_name) {
        ListIterator<SyntaxWord> iterator = stack.listIterator(stack.size());
        while (iterator.hasPrevious()){
            SyntaxWord previous = iterator.previous();
            if (previous.getToken().getContent().equals(ident_name)){
                return previous;
            }
        }
        return null;
    }

    private String GepIrDim2(String res, String len, String var1, String  var2){
        return  tab+res+" = getelementptr ["+len+" x i32], ["+len+" x i32]* "+var1+", i32 0, i32 "+var2;
    }

    private void PropagationLVal(SyntaxWord ast, String reg1, String reg2){
        writeRes(new LoadIR(reg1, reg2) + "\n");
        ast.setValue(reg1);
        ast.setRegId(reg2);
        regId++;
    }

    private boolean isNum(String regValue){
        if(regValue.length() == 0){
            return false;
        }
        boolean flag = false;
        char[] s = regValue.toCharArray();
        int i = 0;
        if(s[0] == '-'){
            i++;
        }
        for (;i<s.length;i++){
            char c = s[i];
            if('0' <= c && c <= '9'){
                flag = true;
            }else{
                return false;
            }
        }
        return flag;
    }

}
